package com.xxb.datasource.aop;

import com.xxb.datasource.consts.DataSourceConstants;
import com.xxb.datasource.utils.DynamicDataSourceContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;


/**
 * 切面
 */
@Aspect
@Component
public class DynamicDataSourceAspect {
    // 以在类上使用了@Service作为切入点
    @Pointcut("@annotation(com.xxb.datasource.aop.XDataSource)")
    public void dataSourcePointCut() {
    }

    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 拿到 方法 的句柄
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 拿到 类 的句柄
        Class<?> aClass = Class.forName(signature.getDeclaringType().getName());
        // todo 方法优先，如果方法上存在注解，则优先使用方法上的注解
        if (signature.getMethod().isAnnotationPresent(XDataSource.class)) {
            DynamicDataSourceContextHolder.setContextKey(signature.getMethod().getAnnotation(XDataSource.class).value());
            // todo 其次类优先，如果类上存在注解，则使用类上的注解
        } else if (aClass.isAnnotationPresent(XDataSource.class)) {
            DynamicDataSourceContextHolder.setContextKey(aClass.getAnnotation(XDataSource.class).value());
            // todo 如果都不存在，则使用默认
        } else {
            DynamicDataSourceContextHolder.setContextKey(DataSourceConstants.DS_KEY_MASTER);
        }
        try {
            // todo 执行方法
            return joinPoint.proceed();
        } finally {
            // todo 防止内存泄漏
            DynamicDataSourceContextHolder.removeContextKey();
        }
    }
}
